﻿using Microsoft.Extensions.DependencyInjection;
namespace 服务定位器
{
    internal class Program
    {
        static void Main(string[] args)
        {
            ServiceCollection services = new ServiceCollection();

            //注册方式一：
            services.AddScoped<ITest, Test1>();

            //注册方式二：这种方式适合于需要复杂构造函数参数的情况
            services.AddScoped<ITest>(sp => new Test1());

            //注册方式三：
            services.AddScoped(typeof(Test1));

            //注册方式四：
            services.AddScoped(typeof(ITest), typeof(Test1));

            //注册方式五：注册多个实现
            services.AddScoped<ITest, Test2>();

            using (ServiceProvider sp = services.BuildServiceProvider())
            {
                //GetRequiredService 的类型参数是注册类型，而不是实现类型
                //GetService 如果没有找到对应的服务注册，则返回 null，而 GetRequiredService 则会抛出异常。
                ITest test1 = sp.GetRequiredService<ITest>();
                test1.SayHi();
                Console.WriteLine(test1.GetType());     // 输出 Test1或者Test2 类型（以最后一次注册的实现为准）
                                                        // GetType：输出具体的实现类型，即使变量类型是接口类型，实际运行时的类型也是具体实现类的类型。

                // 使用另一种注册方式获取服务实例
                //但不推荐这种方式，推荐使用泛型版本。除非是使用反射动态获取类型。（比如写框架的时候）
                ITest test2 = (ITest)sp.GetService(typeof(ITest));

                Console.WriteLine("========================\n\n\n");
                //获取所有注册的实现
                var allTests = sp.GetServices<ITest>();
                foreach (var test in allTests)
                {
                    test.SayHi();
                    Console.WriteLine(test.GetType());
                }
            }
        }
    }

    interface ITest
    {
        public string Name { get; set; }
        void SayHi();
    }

    class Test1 : ITest
    {
        public string Name { get; set; } = "初识依赖注入";
        public void SayHi()
        {
            Console.WriteLine($"Hi, I am {Name} from Test1");
        }
    }

    class Test2 : ITest
    {
        public string Name { get; set; } = "依赖注入示例";
        public void SayHi()
        {
            Console.WriteLine($"Hi, I am {Name} from Test2");
        }
    }
}
